package  com.wmm.job.server;

import  com.wmm.job.model.UserMessage;
import com.wmm.job.student.*;
import com.wmm.job.test.ManageTest;
import com.wmm.job.test.TestItem;

import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

/**
 * 编程实现服务器的主功能
 */
public class ServerView {

    /**
     * 使用合成复用原则
     */
    private ServerInitClose sic;
    private ServerDao sd;
    private ManageStudent manageStudent;
    private ManageTest manageTest;
    private List<TestItem> testItemList = new LinkedList<>();
    /**
     * 用于从客户端接收消息的集合
     */
    private HashMap<String, Object> fromData;
    /**
     * 用于向客户端发送消息的集合
     */
    private HashMap<String, Object> toData;

    /**
     * 通过构造方法实现成员变量的初始化
     * @param sic
     */
    public ServerView(ServerInitClose sic, ServerDao sd) {
        this.sic = sic;
        this.sd = sd;
    }

    /**
     * 自定义成员方法实现客户端发来消息的接收并处理
     */
    public void serverReceive()  {
        boolean flag = true;
        DaoStudent daoStudent = null;
        // 1.创建一个集合用于存储所有学生信息
        List<Student> studentList = new LinkedList<>();
        daoStudent = new DaoStudent(studentList);
        try {
            // 3.当系统启动时读取文件中所有学生信息到List集合中
            studentList = daoStudent.readStudentList();
            // 2.通过集合进行学生信息的增删改查操作
            manageStudent = new ManageStudent(studentList);
            manageTest = new ManageTest(testItemList);
            while (flag) {
                fromMessage();
                service();
                toMessage();
            }

            daoStudent.writeStudentList();

        }catch (Exception e){
            e.printStackTrace();
        }
    }


    /**
     * 处理接收到的数据
     */
    private void service() throws AgeException, IdException {
        // 取出消息类型
        Integer type = (Integer) fromData.get("type");
        // 根据不同的消息类型, 执行不同的逻辑处理
        switch (type) {
            case 1://学生
                UserMessage user = (UserMessage)fromData.get("data");
                if (manageStudent.checkStudent(Integer.parseInt(user.getUser().getUserName()),user.getUser().getPassword())){
                    System.out.println("登录成功");
                    user.setType("success");
                    setToData(1,user);
                }else {
                    System.out.println("登录失败");
                    user.setType("fail");
                    setToData(0,user);
                }
                break;
            case 11://修改信息
                Student s1 = (Student)fromData.get("data");
                if (manageStudent.modifyStudent(s1.getId(), s1.getAge(),s1.getName())){
                    setToData(1,s1);
                }else {
                    setToData(0,s1);
                }
                break;
            case 12://开始考试
                setToData(1,manageTest.getTestList());
                break;
            case 13://查询考试成绩
                String id1 = fromData.get("data").toString();
                int score =  manageStudent.getStudentScore(Integer.parseInt(id1));
                if (score != -1){
                    setToData(1,score);
                }else {
                    setToData(0,0);
                }
                break;
            case 14://修改密码
                Student st1 = (Student) fromData.get("data");
                if(manageStudent.modifyStudentPassWord(st1.getId(),st1.getPassWord())){
                    setToData(1,st1);
                }else{
                    setToData(0,st1);
                }
                break;
            case 15://记录得分
                Student st2 = (Student) fromData.get("data");
                if (manageStudent.modifyStudentScore(st2.getId(),st2.getSocre())){
                    setToData(1,st2);
                }else{
                    setToData(1,st2);
                }
                break;
            case 2:// 管理员
                // 相同的套路
                // 1. 接收传递的data数据
                UserMessage us = (UserMessage) fromData.get("data");
                if (us.getType().equals("managerCheck")) {
                    // 调用方法实现管理员账号和密码信息的校验
                    if (sd.serverManagerCheck(us.getUser())) {
                        us.setType("success");
                        setToData(1,us);
                    } else {
                        us.setType("fail");
                        setToData(0,us);
                    }
                }
                // 3. 根据Service操作数据库的返回值, 向toData中填充指定的数据
                break;
            case 211://学生增加
                Student st = (Student) fromData.get("data");
                if(manageStudent.addStudent(st)){
                    setToData(1,st);
                }else {
                    setToData(0,st);
                }
                break;
            case 212://删除学生
                String id = fromData.get("data").toString();
                if (manageStudent.deleteStudent(Integer.parseInt(id))){
                    setToData(1,id);
                }else{
                    setToData(0,id);
                }
                break;
            case 213://修改学生信息
                Student s = (Student)fromData.get("data");
                if (manageStudent.modifyStudent(s.getId(), s.getAge(),s.getName())){
                    setToData(1,s);
                }else {
                    setToData(0,s);
                }
                break;
            case 214://查找学生
                Integer studentId = (Integer) fromData.get("data");
                Student stu = manageStudent.queryStudent(studentId);
                if (stu == null){
                    setToData(0,null);
                }else {
                    setToData(1,stu);
                }
                break;
            case 221:
                TestItem item = (TestItem) fromData.get("data");
                if(manageTest.addItem(item)){
                    setToData(1,item);
                }else {
                    setToData(0,item);
                }
                break;
            case 222:
                String testID = fromData.get("data").toString();
                if (manageTest.deleteItem(Integer.parseInt(testID))){
                    setToData(1,testID);
                }else{
                    setToData(0,testID);
                }
                break;
            case 223:
                TestItem item1 = (TestItem) fromData.get("data");
                if (manageTest.modifyItem(item1)){
                    setToData(1,item1);
                }else {
                    setToData(0,item1);
                }
                break;
            case 224:
                Integer itemId = (Integer) fromData.get("data");
                TestItem testItem = manageTest.queryItem(itemId);
                if (testItem == null){
                    setToData(0,null);
                }else {
                    setToData(1,testItem);
                }
                break;
        }
    }


    /**
     * 接收客户端消息
     *
     * @throws Exception
     */
    // @SuppressWarnings("unchecked")
    private void fromMessage() throws Exception {
        fromData = (HashMap<String, Object>) sic.getOis().readObject();
        System.out.println("服务器收到客户端"+fromData.get("type")+"消息");
    }

    private void toMessage() throws Exception {
        sic.getOos().writeObject(toData);
        System.out.println("服务器向客户端"+toData.get("type")+"发出消息" );
        sic.getOos().flush();
    }

    /**
     * 用于向toData中填充要发送的数据 ,在每次填充时, 会重新创建toData对象 !
     *
     * @param type
     * @param data
     */
    private void setToData(int type, Object data) {
        toData = new HashMap<>();
        toData.put("type", type);
        toData.put("data", data);
    }
}
